// Image Library
//
// Copyright (C) 1997-1998, Earl F. Glynn, Overland Park, KS  USA.
// All Rights Reserved.

UNIT ImageLib;

INTERFACE

  USES
    Windows;    //  TRGBTriple

  CONST
    MaxPixelCount   =  32768;

  TYPE
    pRGBArray  =  ^TRGBArray;    // Use SysUtils.pByteArray for 8-bit color
    TRGBArray  =  ARRAY[0..MaxPixelCount-1] OF TRGBTriple;


  PROCEDURE RGBtoHSV (CONST r,g,b:  INTEGER;   {0..255}
                      VAR   h,s,v:  INTEGER);  {h IN 0..359; s,v IN 0..255}

IMPLEMENTATION

  // Optimize getting min and max for only three values:
  // no loops and minimum comparisons
  PROCEDURE MinMax3(CONST i,j,k:  INTEGER; VAR min, max:  INTEGER);
  BEGIN
    IF   i > j
    THEN BEGIN
      IF   i > k
      THEN max := i
      ELSE max := k;

      IF   j < k
      THEN min := j
      ELSE min := k
    END
    ELSE BEGIN
      IF   j > k
      THEN max := j
      ELSE max := k;

      IF   i < k
      THEN min := i
      ELSE min := k
    END
  END {MinMax3};


  // RGB, each 0 to 255, to HSV.
  //  H = 0 to 359 degrees around color circle
  //  S = 0 (shade of gray) to 255 (pure color)
  //  V = 0 (black) to 255 {white)
  //
  //  Based on C Code in "Computer Graphics -- Principles and Practice,"
  //  Foley et al, 1996, p. 592.  Floating point fractions, 0..1, replaced with
  //  integer values, 0..255.

  PROCEDURE RGBtoHSV (CONST r,g,b:  INTEGER;   {0..255}
                      VAR   h,s,v:  INTEGER);  {h IN 0..359; s,v IN 0..255}
    VAR
      Delta   :  INTEGER;
      MinValue:  INTEGER;
  BEGIN
    MinMax3(R, G, B, MinValue, v);
    Delta := v - MinValue;

    // Calculate saturation:  saturation is 0 if r, g and b are all 0
    IF   v = 0
    THEN s := 0
    ELSE s := (255 * Delta) DIV v;

    IF   s = 0
    THEN h := 0   // Achromatic:  When s = 0, h is undefined but assigned the value 0
    ELSE BEGIN    // Chromatic

      IF   r = v
      THEN h := (60*(g-b)) DIV Delta             // degrees -- between yellow and magenta
      ELSE
        IF   g = v
        THEN h := 120 + (60*(b-r)) DIV Delta     // degrees -- between cyan and yellow
        ELSE
          IF  b = v
          THEN h := 240 + (60*(r-g)) DIV Delta;  // degrees -- between magenta and cyan

      IF   h < 0
      THEN h := h + 360;

    END
  END {RGBtoHSV};

END {ImageLib}.
